﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bingosoft.RestService.Attributes;
using Bingosoft.Data;
using Bingosoft.OAuth.Client.Token.Grant.Code;
using BingoSoft.Oauth.Client;
using Bingosoft.OAuth.Client.SSO;
using Bingosoft.OAuth.Client;
using MobileServer.Bll.Common;
using System.Configuration;
using Bingosoft.Web.Utils;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Utility;
using System.IO;
using System.Web;
using SyncBingosoftUsers.Utiltiy;
using NLog;

namespace MobileServer.Bll.Bis
{
    [Service("BisService")]
    public class BisService : ServiceBase
    {
        protected String resourceBaseUri = "dataservice.ashx?CommandName=BisService$";
        private UserService userService = new UserService();
        private ActivityService activityService = new ActivityService();

        Dao dao = Dao.Get();
        private Logger logger = LogManager.GetCurrentClassLogger();

        public BisService()
        {

        }

        [ServiceMethod]
        public bool ExistUser(string username)
        {
            return Dao.Get().QueryScalar<int>("Security.User.Exist", new { LoginId = username }) > 0;
        }

        #region 首页
        [ServiceMethod]
        public ViewModel<List<ActivityInfo>> GetActivityList()
        {
            return new ViewModel<List<ActivityInfo>>(200, "", activityService.GetActivitysWithoutEnd());
        }

        [ServiceMethod]
        public ViewModel<HomeDTO> GetHomeDTO(string username)
        {
            HomeDTO dto = new HomeDTO() { PrevActivityUsers = new ActivityUserInfo[] { } };
            dto.UserInfo = dao.QueryEntity<UserInfo>("Security.GetUserByLoginId", new { LoginId = username });
            dto.LastUserLog = dao.QueryEntity<UserLogInfo>("User.GetLastUserLog", new { UserID = dto.UserInfo.Id });
            dto.LastActivityInfo = dao.QueryEntity<ActivityInfo>("Activity.GetLastActivity");
            var prevActivityInfo = dao.QueryEntity<ActivityInfo>("Activity.GetPrevActivity", new { StartDate = dto.LastActivityInfo.StartDate });
            if (prevActivityInfo != null)
            {
                dto.PrevActivityUsers = dao.QueryEntities<ActivityUserInfo>("Activity.ActivityUsers", new { ActivityId = prevActivityInfo.Id }).ToArray();
                foreach (var pau in dto.PrevActivityUsers)
                    pau.UserInfo = dao.QueryEntity<UserInfo>("Security.Get", new { Id = pau.UserID });
            }

            return new ViewModel<HomeDTO>(200, "", dto);
        }
        #endregion

        #region 当前活动页
        [ServiceMethod]
        public ViewModel<List<ActivityUserInfo>> GetActivityUsers(string activityId)
        {
            return new ViewModel<List<ActivityUserInfo>>(200, string.Empty, 
                activityService.GetActivityUsers(activityId));
        }
        [ServiceMethod]
        public ViewModel<ActivityInfo> GetActivity(string activityId)
        {
            return new ViewModel<ActivityInfo>(200, string.Empty, dao.QueryEntity<ActivityInfo>("Activity.GetActivity", new { Id = activityId }));
        }


        [ServiceMethod]
        public ViewModel<ActivityDTO> GetActivityDTO(string username)
        {
            ActivityDTO dto = new ActivityDTO();
            
            Dao dao = Dao.Get();
            
            dto.UserInfo = dao.QueryEntity<UserInfo>("Security.GetUserByLoginId", new { LoginId = username });
            dto.LastActivityInfo = dao.QueryEntity<ActivityInfo>("Activity.GetLastActivity");
            if (dto.LastActivityInfo != null)
            {
                dto.ActivityUsers = dao.QueryEntities<ActivityUserInfo>("Activity.ActivityUsers", new { ActivityId = dto.LastActivityInfo.Id }).ToArray();
                foreach (var pau in dto.ActivityUsers)
                    pau.UserInfo = dao.QueryEntity<UserInfo>("Security.Get", new { Id = pau.UserID });
            }

            return new ViewModel<ActivityDTO>(200, string.Empty, dto);
        }

        [ServiceMethod]
        public ViewModel<UserLogInfo[]> GetUserLogs(string username)
        {

            UserLogInfo[] dto = userService.GetUserLogs(username);


            return new ViewModel<UserLogInfo[]>(200, string.Empty, dto);
        }
        #endregion

        #region 用户账户页
        [ServiceMethod]
        public ViewModel<AccountDTO> GetAccountDTO(string username)
        {
            AccountDTO dto = new AccountDTO();

            Dao dao = Dao.Get();

            dto.UserInfo = dao.QueryEntity<UserInfo>("Security.GetUserByLoginId", new { LoginId = username });
            dto.UserLogs = dao.QueryEntities<UserLogInfo>("User.NewsGetUserLogs", new { UserID = dto.UserInfo.Id }).ToArray();

            return new ViewModel<AccountDTO>(200, string.Empty, dto);
        }
        #endregion

        #region 联系我们

        [ServiceMethod]
        public ViewModel<UserInfo[]> GetContactDTO()
        {
            UserInfo[] dto = new UserInfo[] { };

            dto = Dao.Get().QueryEntities<UserInfo>("Security.GetAdminUsers").ToArray();

            return new ViewModel<UserInfo[]>(200, string.Empty, dto);
        }
        #endregion

        #region 报名、签到功能
        /// <summary>
        /// 签到
        /// </summary>
        /// <param name="ActivityUserId"></param>
        [ServiceMethod]
        public ViewModel<object> SignIn(string activityUserId)
        {
            return ExecNonCommand(() =>
            {
                userService.SetSignIn(activityUserId);
            });
        }

        /// <summary>
        /// 报名
        /// </summary>
        /// <param name="ActivityUserId"></param>
        [ServiceMethod]
        public ViewModel<object> Enter(string LoginId, string ActivityId)
        {
            return ExecNonCommand(() =>
            {
                userService.SetEnter(ActivityId, LoginId);
            });
        }

        [ServiceMethod]
        public ViewModel<object> Close(string activityId)
        {
            return ExecNonCommand(() =>
            {
                dao.ExecuteNonQuery("Activity.Close", new { ActivityId = activityId });
            });
        }

        /// <summary>
        /// 撤销报名
        /// </summary>
        /// <param name="ActivityUserId"></param>
        [ServiceMethod]
        public ViewModel<object> Cancel(string LoginId, string ActivityId)
        {
            return ExecNonCommand(() =>
            {
                userService.SetNotEnter(ActivityId, LoginId);
            });
        }

        #endregion

        #region 娱乐功能

        /// <summary>
        /// 抢钱
        /// </summary>
        /// <param name="FromActivityUserId"></param>
        /// <param name="ToActivityUserId"></param>
        [ServiceMethod]
        public ViewModel<object> Robbed(string ActivityUserId, string FromUserId)
        {
            return ExecNonCommand(() =>
            {
                userService.Robbed(ActivityUserId, FromUserId);
            });
        }

        /// <summary>
        /// 鄙视
        /// </summary>
        /// <param name="FromActivityUserId"></param>
        /// <param name="ToActivityUserId"></param>
        [ServiceMethod]
        public ViewModel<object> Despises(string FromUserId, string ToUserId)
        {
            return ExecNonCommand(() =>
            {
                userService.Despises(FromUserId, ToUserId);
            });
        }


        #endregion


        private ViewModel<object> ExecNonCommand(Action act)
        {
            try
            {
                act();
                return new ViewModel<object>(200);
            }
            catch (BisException bisex)
            {
                logger.ErrorException("执行错误", bisex);
                return new ViewModel<object>(888, "×_× 不好意思，" + bisex.Message + "!");
            }
        }


        //财务功能
        [ServiceMethod]
        public ViewModel<double[]> GetAmount()
        {
            //{协会总额,总余额,经费总额,经费余额,会费总额,会费余额}

            double[] amount = new double[6];

            amount[0] = dao.QueryScalar<float>("Balance.SumAmount", new { Type = new[] { 5, 9 } });//协会总额
            amount[1] = dao.QueryScalar<float>("Balance.SumAmount");//协会总余额额

            //经费总额
            amount[2] = dao.QueryScalar<float>("Balance.SumAmount", new { Type = new[] { 5 }, Month = DateTime.Now.Month, Year = DateTime.Now.Year });
            //当月消费
            double monthConsume = dao.QueryScalar<float>("Balance.SumAmount", new { Type = new[] { 0 }, Month = DateTime.Now.Month, Year = DateTime.Now.Year });

            //经费余额(经费总额-当月消费)，用光时或超出时返回0
            amount[3] = amount[2] - Math.Abs(monthConsume);
            if (amount[3] < 0) amount[3] = 0;

            amount[4] = dao.QueryScalar<float>("Balance.SumAmount", new { Type = new[] { 9 } });//会费总额
            //各月累计超过部分
            double excess = GetExcess();
            amount[5] = amount[4] - Math.Abs(excess); //会费余额（会费总额-各月累计超出部分)

            //using (var reader = dao.QueryReader("Balance.GetAmount"))
            //var amountCollection = new List<uint[]>();
            //using (var reader = dao.QueryReader("select [Type], Sum(Amount) AS Amount, DATEPART(M, UpdateTime) from Bis_Balance group by [Type], DATEPART(M, UpdateTime)"))
            //{
            //    while (reader.Read())
            //    {
            //        amountCollection.Add(new uint[] { (uint)reader[0], (uint)reader[1], (uint)reader[2] });

            //        double val = (double)reader[1];
            //        switch ((int)reader[0])
            //        {
            //            case 0:
            //                consume = val; break;
            //            case 5:
            //                amount[2] = val;break;
            //            case 9:
            //                amount[4] = val; break;
            //        }
            //    }
            //}

            ////总金额、总余额
            //amount[0] = amount[2] + amount[4];
            //amount[1] = amount[0] + consume;

            ////当经费余额足以支付总消费额时，优先从经费里支出。
            ////当经费不足时，从会费总额里扣。
            //amount[3] = ((amount[2] - Math.Abs(consume)) < 0 ? 0 : (amount[2] + consume));
            //amount[5] = ((amount[2] - Math.Abs(consume)) < 0 ? (amount[4] + amount[2] + consume) : amount[4]);

            return new ViewModel<double[]>(200, "", amount);
        }

        private double GetExcess()
        {
            double val = 0;
            using (var reader = dao.QueryReader("Balance.Excess"))
            {
                while (reader.Read())
                {
                    double excess = 0;
                    double.TryParse(reader["Excess"].ToString(), out excess);
                    if (excess < 0)
                    {
                        val += excess;
                    }
                }
            }

            return val;
        }

        [ServiceMethod]
        public ViewModel<List<object>> GetActivityFinanceList()
        {
            List<object> objs = new List<object>();
            using (var reader = dao.QueryReader("Balance.GetActivityFinanceList"))
            {
                while (reader.Read())
                {
                    objs.Add(new { ID = reader[0], StartDate = reader[1], Amount = reader[2], UserCount = reader[3] });
                }
            }
            return new ViewModel<List<object>>(200, "", objs);
        }

        [ServiceMethod]
        public ViewModel<List<object>> GetMonthFinance()
        {
            List<object> objs = new List<object>();
            using (var reader = dao.QueryReader("Balance.Excess"))
            {
                while (reader.Read())
                {
                    double excess = 0;
                    double.TryParse(reader["Excess"].ToString(), out excess);

                    if (excess > 0) excess = 0;
                    objs.Add(new
                    {
                        Month = reader["Month"],
                        Subsidy = reader["Subsidy"],
                        Consume = reader["Consume"],
                        Excess = Math.Abs(excess)
                    });
                }
            }
            return new ViewModel<List<object>>(200, "", objs);
        }

        [ServiceMethod]
        public ViewModel<List<object>> GetActivityFinanceUser(string activityId)
        {
            List<object> objs = new List<object>();
            using (var reader = dao.QueryReader("Balance.GetActivityFinanceUser", new { ActivityId = activityId }))
            {
                while (reader.Read())
                {
                    objs.Add(new
                    {
                        ID=reader["ID"],
                        ActivityId = reader["ActivityId"],
                        Title= reader["Title"],
                        UserId = reader["UserID"],
                        Name = reader["Name"],
                        Amount = reader["Amount"]

                    });
                }
            }
            return new ViewModel<List<object>>(200, "", objs);
        }

        [ServiceMethod]
        public ViewModel<List<object>> GetUserList()
        {
            List<object> objs = new List<object>();
            using (var reader = dao.QueryReader("Security.GetUsers"))
            {
                while (reader.Read())
                {
                    objs.Add(new { Id = reader["Id"], Name = reader["Name"], AttendTimes = reader["AttendTimes"], Amount = reader["Amount"], Consume = reader["Consume"] });
                }
            }
            return new ViewModel<List<object>>(200, "", objs);
        }

        [ServiceMethod]
        public ViewModel<object> GetUserAccountById(string userId)
        {
            object objs = new object();
            using (var reader = dao.QueryReader("Balance.UserAccount", new { UserId = userId }))
            {
                if (reader.Read())
                {
                    objs = new
                    {
                        Id = reader["Id"],
                        Name = reader["Name"],
                        Face = reader["Face"],
                        MobilePhone = reader["MobilePhone"],
                        Consume = reader["Consume"] == DBNull.Value ? 0 : Convert.ToDouble(reader["Consume"]),
                        Balance = reader["Balance"] == DBNull.Value ? 0 : Convert.ToDouble(reader["Balance"]),
                        AttendTimes = Convert.ToInt32(reader["AttendTimes"]),
                        CreatedDate = reader["CreatedDate"]
                    };
                }
            }
            return new ViewModel<object>(200, "", objs);

        }

        [ServiceMethod]
        public void UpdateFace()
        {
            string facePath = HttpContext.Current.Server.MapPath("~/Face/");
            if (!Directory.Exists(facePath))
                Directory.CreateDirectory(facePath);
            Bingosoft.Common.Logging.LogManager.GetCurrentClassLogger().Debug(facePath);
            var items = dao.QueryDictionaries("select id, ThumbnailPhoto from SEC_User");
            foreach (var dict in items)
            {
                string key = dict["id"].ToString();
                if(dict["ThumbnailPhoto"] == System.DBNull.Value)
                    continue;
                byte[] value = (byte[])dict["ThumbnailPhoto"];
                string name = key + ".jpg";
                string fileName = Path.Combine(facePath, name);
                if (value != null)
                    if (CreateFace(fileName, value))
                        dao.ExecuteNonQuery("update SEC_User set Face=#Face# where Id = #Id#", new { Face = "face/" + name, Id = key });
            }
        }

        private bool CreateFace(string fileName, byte[] bytes)
        {
            try
            {
                if (bytes != null)
                    Bytes2Image.ReturnPhoto(bytes).Save(fileName);
                return true;
            }
            catch (Exception ex)
            {
                Bingosoft.Common.Logging.LogManager.GetCurrentClassLogger().Error("", ex);
                return false;
            }
        }
    }
}
